#include "VSettingDialog.h"
#include "ui_VSettingDialog.h"
#include "VJsonItemWidget.h"
#include "VJsonSettingDilg.h"
#include "VGlobal.h"
#include "VFunctions.h"

#include <QDir>
#include <QFileInfo>
#include <QListView>
#include <QDebug>
#include <QRegularExpression>
#include <QMouseEvent>
#include <QJsonObject>
#include <QJsonArray>
#include <QJsonValue>
#include <QJsonDocument>
#include <QTreeWidgetItem>
#include <QBrush>
#include <QSpinBox>
#include <QDebug>
#include <QRegExp>

VSettingDialog::VSettingDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::VSettingDialog)
{
    ui->setupUi(this);
    ui->shortcut_treewidget->setColumnWidth(0, 250);

    // 皮肤关联
    connect(ui->combobox_skin, &QComboBox::currentTextChanged, this, &VSettingDialog::update_color_listwidget);

    // 设定颜色关联
    connect(ui->checkbox_bold, &QCheckBox::clicked, this, &VSettingDialog::update_color_listwidget_item);
    connect(ui->checkbox_italic, &QCheckBox::clicked, this, &VSettingDialog::update_color_listwidget_item);
    connect(ui->frame_fore, &VColorSelect::signal_color_changed, this, &VSettingDialog::update_color_listwidget_item);
    connect(ui->frame_back, &VColorSelect::signal_color_changed, this, &VSettingDialog::update_color_listwidget_item);

    // 字体改变
    connect(ui->fontc_textedit, &QFontComboBox::currentTextChanged, this, &VSettingDialog::update_color_listwidget_font);
    connect(ui->spinbox_textedit_font_size, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged)
            , this, &VSettingDialog::update_color_listwidget_font);

    // 代码排版关联
    connect(ui->spinbox_tab_width, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged)
            , this, &VSettingDialog::update_code_format_summary);
    connect(ui->checkbox_for_after_add_space, &QCheckBox::clicked, this, &VSettingDialog::update_code_format_summary);
    connect(ui->checkbox_function_after_add_space, &QCheckBox::clicked, this, &VSettingDialog::update_code_format_summary);
    connect(ui->checkbox_if_after_add_space, &QCheckBox::clicked, this, &VSettingDialog::update_code_format_summary);
    connect(ui->checkbox_kr, &QCheckBox::clicked, this, &VSettingDialog::update_code_format_summary);
    connect(ui->checkbox_while_after_add_space, &QCheckBox::clicked, this, &VSettingDialog::update_code_format_summary);
    connect(ui->checkbox_delete_surplus_line, &QCheckBox::clicked, this, &VSettingDialog::update_code_format_summary);
    connect(ui->checkbox_else_close_to_brackets, &QCheckBox::clicked, this, &VSettingDialog::update_code_format_summary);
    connect(ui->checkbox_if_down_line_add_brackets, &QCheckBox::clicked, this, &VSettingDialog::update_code_format_summary);
    connect(ui->checkbox_user_tab, &QCheckBox::clicked, this, &VSettingDialog::update_code_format_summary);
    connect(ui->lineedit_codeformat_other_control, &QLineEdit::textChanged, this, &VSettingDialog::update_code_format_summary);

    load_setting(VGlobal::config_dir + "/setting.json");
    if(ui->combobox_skin->currentText().isEmpty() == false)
        load_color_setting(VGlobal::skins_dir + "/" + ui->combobox_skin->currentText() + "/scintilla.json");
}

VSettingDialog::~VSettingDialog()
{
    delete ui;
}

void VSettingDialog::update_color_listwidget_item()
{
    auto item = ui->color_listwidget->currentItem();
    if(item == nullptr) return;

    QString fore = ui->frame_fore->_color;
    QString back = ui->frame_back->_color;
    bool bold = ui->checkbox_bold->isChecked();
    bool italic = ui->checkbox_italic->isChecked();
    item->setForeground(QBrush(QColor(fore.toInt(nullptr, 16))));
    item->setBackground(QBrush(QColor(back.toInt(nullptr, 16))));

    QFont font = item->font();
    font.setBold(bold);
    font.setItalic(italic);

    item->setFont(font);
}

void VSettingDialog::update_color_listwidget_font()
{

    QString name = ui->fontc_textedit->currentText();
    if(name.isEmpty()) return;

    for(int i=0; i<ui->color_listwidget->count(); i++)
    {
        auto item = ui->color_listwidget->item(i);
        QFont font = item->font();
        font.setFamily(name);
        font.setPixelSize(ui->spinbox_textedit_font_size->value()+3);
        item->setFont(font);
    }
}

void VSettingDialog::update_code_format_summary()
{
    QStringList list;
    list.append(QString("-i%1").arg(ui->spinbox_tab_width->value()));

    if(ui->checkbox_kr->isChecked())
    {
        list.append("-kr");
    }

    if(ui->checkbox_function_after_add_space->isChecked())
        list.append("-bap");
    else
        list.append("-nbap");

    if(ui->checkbox_if_after_add_space->isChecked())
        list.append("-sai");
    else
        list.append("-nsai");

    if(ui->checkbox_for_after_add_space->isChecked())
        list.append("-saf");
    else
        list.append("-nsaf");

    if(ui->checkbox_while_after_add_space->isChecked())
        list.append("-saw");
    else
        list.append("-nsaw");

    if(ui->checkbox_user_tab->isChecked())
        list.append("-ut");

    if(ui->checkbox_delete_surplus_line->isChecked())
        list.append("-sob");
    else
        list.append("-nsob");

    if(ui->checkbox_else_close_to_brackets->isChecked())
        list.append("-ce");
    else
        list.append("-nce");

    if(ui->checkbox_if_down_line_add_brackets->isChecked())
        list.append("-bl");
    else
        list.append("-br");

    QString other = ui->lineedit_codeformat_other_control->text();
    other = other.replace(QRegExp("\\s+"), " ");
    foreach(QString str, other.split(' '))
    {
        if(str.isEmpty() == false)
            list.append(str);
    }

    ui->textedit_codeformat_summary->setPlainText(list.join(';'));
}

void VSettingDialog::on_color_listwidget_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous)
{
    ui->frame_fore->set_color(current->foreground().color());
    ui->frame_back->set_color(current->background().color());

    QFont font;
    font =  current->font();
    ui->checkbox_bold->setChecked(font.bold());
    ui->checkbox_italic->setChecked(font.italic());

    QString mark = current->data(Qt::UserRole).value<QString>();
    font = ui->label_fore->font();
    if(mark.indexOf("fore") != -1)
        font.setStrikeOut(false);
    else
        font.setStrikeOut(true);
    ui->label_fore->setFont(font);

    font = ui->label_back->font();
    if(mark.indexOf("back") != -1)
        font.setStrikeOut(false);
    else
        font.setStrikeOut(true);
    ui->label_back->setFont(font);

    font = ui->checkbox_bold->font();
    if(mark.indexOf("bold") != -1)
        font.setStrikeOut(false);
    else
        font.setStrikeOut(true);
    ui->checkbox_bold->setFont(font);

    font = ui->checkbox_italic->font();
    if(mark.indexOf("italic") != -1)
        font.setStrikeOut(false);
    else
        font.setStrikeOut(true);
    ui->checkbox_italic->setFont(font);


}

void VSettingDialog::on_btn_modify_shortcut_clicked()
{
    auto item = ui->shortcut_treewidget->currentItem();
    if(item == nullptr) return;
    if(item->parent() == nullptr) return;

    item->setText(1, ui->lineedit_shortcut->text());
}

void VSettingDialog::on_shortcut_treewidget_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous)
{
    if(current->parent() == nullptr)
    {
        ui->lineedit_shortcut->clear();
        return;
    }
    ui->lineedit_shortcut->setText(current->text(1));
}

void VSettingDialog::on_btn_yes_clicked()
{
    save_setting(VGlobal::config_dir + "/setting.json");
    if(ui->combobox_skin->currentText().isEmpty() == false)
        save_color_setting(VGlobal::skins_dir + "/" + ui->combobox_skin->currentText() + "/scintilla.json");
    this->accept();
}

void VSettingDialog::update_color_listwidget(QString name)
{
    load_color_setting(VGlobal::skins_dir + "/" + name + "/scintilla.json");
}

QString VSettingDialog::makeColorString(const QColor &color, const QString type)
{
    if(type == "RGBA") {
        return QString("rgba(%1, %2, %3, %4)")
                .arg(color.red())
                .arg(color.green())
                .arg(color.blue())
                .arg(color.alpha());
    }
    if(type == "RGB") {
        return QString("rgba(%1, %2, %3)")
                .arg(color.red())
                .arg(color.green())
                .arg(color.blue());
    }
    if(type == "HEX") {
        return QString().sprintf("%02X%02X%02X",
                                 color.red(),
                                 color.green(),
                                 color.blue());
    }

    return color.name();
}

void VSettingDialog::save_setting(QString path)
{
    QJsonObject parent;
    QJsonObject app;
    app.insert("skin", QJsonValue(ui->combobox_skin->currentText()));
    app.insert("font", QJsonValue(ui->fontc_app->currentText()));
    parent.insert("app", QJsonValue(app));

    QJsonObject code_edit;
    code_edit.insert("font", QJsonValue(ui->fontc_textedit->currentText()));
    code_edit.insert("font_size", QJsonValue(ui->spinbox_textedit_font_size->value()));
    code_edit.insert("tab_width", QJsonValue(ui->spinbox_tab_width->value()));
    code_edit.insert("symbol", QJsonValue(ui->checkbox_symbol->isChecked()?"true":"false"));
    parent.insert("code_edit", QJsonValue(code_edit));

    QJsonObject code_format;
    code_format.insert("checkbox_kr", QJsonValue(ui->checkbox_kr->isChecked()?"true":"false"));
    code_format.insert("checkbox_for_after_add_space", QJsonValue(ui->checkbox_for_after_add_space->isChecked()?"true":"false"));
    code_format.insert("checkbox_function_after_add_space", QJsonValue(ui->checkbox_function_after_add_space->isChecked()?"true":"false"));
    code_format.insert("checkbox_if_after_add_space", QJsonValue(ui->checkbox_if_after_add_space->isChecked()?"true":"false"));
    code_format.insert("checkbox_while_after_add_space", QJsonValue(ui->checkbox_while_after_add_space->isChecked()?"true":"false"));
    code_format.insert("checkbox_delete_surplus_line", QJsonValue(ui->checkbox_delete_surplus_line->isChecked()?"true":"false"));
    code_format.insert("checkbox_else_close_to_brackets", QJsonValue(ui->checkbox_else_close_to_brackets->isChecked()?"true":"false"));
    code_format.insert("checkbox_if_down_line_add_brackets", QJsonValue(ui->checkbox_if_down_line_add_brackets->isChecked()?"true":"false"));
    code_format.insert("checkbox_user_tab", QJsonValue(ui->checkbox_user_tab->isChecked()?"true":"false"));
    code_format.insert("other_control", QJsonValue(ui->lineedit_codeformat_other_control->text()));
    code_format.insert("summary", QJsonValue(ui->textedit_codeformat_summary->toPlainText()));
    parent.insert("code_format", QJsonValue(code_format));

    QJsonObject intelligence;
    intelligence.insert("delay", QJsonValue(ui->spinbox_tip_delay->value()));
    parent.insert("intelligence", QJsonValue(intelligence));

    QJsonObject toolbar;
    toolbar.insert("checkbox_std", QJsonValue(ui->checkbox_std->isChecked()?"true":"false"));
    toolbar.insert("checkbox_textedit", QJsonValue(ui->checkbox_textedit->isChecked()?"true":"false"));
    toolbar.insert("checkbox_build", QJsonValue(ui->checkbox_build->isChecked()?"true":"false"));
    toolbar.insert("checkbox_debug", QJsonValue(ui->checkbox_debug->isChecked()?"true":"false"));
    parent.insert("toolbar", QJsonValue(toolbar));

    QJsonArray shortcut_array;
    auto root = ui->shortcut_treewidget->invisibleRootItem();
    for (int i = 0; i < root->childCount(); i++)
    {
        QString type = root->child(i)->text(0);
        QJsonArray item_arr;
        for(int j=0; j<root->child(i)->childCount(); j++)
        {
            QJsonObject object;
            auto item = root->child(i)->child(j);
            QString name = item->text(0);
            QString short_ = item->text(1);
            object.insert("name", QJsonValue(name));
            object.insert("short", QJsonValue(short_));
            item_arr.append(QJsonValue(object));
        }
        QJsonObject object;
        object.insert("项目", QJsonValue(item_arr));
        object.insert("类别", type);
        shortcut_array.append(object);
    }
    parent.insert("快捷键", QJsonValue(shortcut_array));

    VFunctions::save_file(path, QJsonDocument(parent).toJson());
}

void VSettingDialog::save_color_setting(QString path)
{
    // 保存代码编辑框颜色配置
    QJsonArray array;
    for(int i=0; i<ui->color_listwidget->count(); i++)
    {
        auto item = ui->color_listwidget->item(i);
        QString name = item->text();
        QString fore = makeColorString(item->foreground().color(), "HEX");
        QString back = makeColorString(item->background().color(), "HEX");
        QFont font;
        font = item->font();
        QString bold = font.bold()?"true":"false";
        QString italic = font.italic()?"true":"false";
        QString mark = item->data(Qt::UserRole).value<QString>();

        QJsonObject object;
        object.insert("name", QJsonValue(name));
        object.insert("fore", QJsonValue(fore));
        object.insert("back", QJsonValue(back));
        object.insert("bold", QJsonValue(bold));
        object.insert("italic", QJsonValue(italic));
        object.insert("mark", QJsonValue(mark));

        array.append(QJsonValue(object));
    }

    QJsonObject object;
    object.insert("color", QJsonValue(array));
    VFunctions::save_file(path, QJsonDocument(object).toJson());
}

void VSettingDialog::load_setting(QString path)
{
    QJsonObject parent = VFunctions::get_file_jsonDocument(path).object();
    QJsonObject app = parent.value("app").toObject();
    ui->fontc_app->setCurrentText(app.value("font").toString());
    ui->combobox_skin->setCurrentText(app.value("skin").toString());

    QJsonObject code_edit = parent.value("code_edit").toObject();
    ui->fontc_textedit->setCurrentText(code_edit.value("font").toString());
    ui->spinbox_textedit_font_size->setValue(code_edit.value("font_size").toInt());
    ui->checkbox_symbol->setChecked(code_edit.value("symbol") == "true");
    ui->spinbox_tab_width->setValue(code_edit.value("tab_width").toInt());

    QJsonObject code_format = parent.value("code_format").toObject();
    ui->checkbox_delete_surplus_line->setChecked(code_format.value("checkbox_delete_surplus_line") == "true");
    ui->checkbox_else_close_to_brackets->setChecked(code_format.value("checkbox_else_close_to_brackets") == "true");
    ui->checkbox_for_after_add_space->setChecked(code_format.value("checkbox_for_after_add_space") == "true");
    ui->checkbox_function_after_add_space->setChecked(code_format.value("checkbox_function_after_add_space") == "true");
    ui->checkbox_if_after_add_space->setChecked(code_format.value("checkbox_if_after_add_space") == "true");
    ui->checkbox_if_down_line_add_brackets->setChecked(code_format.value("checkbox_if_down_line_add_brackets") == "true");
    ui->checkbox_kr->setChecked(code_format.value("checkbox_kr") == "true");
    ui->checkbox_user_tab->setChecked(code_format.value("checkbox_user_tab") == "true");
    ui->checkbox_while_after_add_space->setChecked(code_format.value("checkbox_while_after_add_space") == "true");
    ui->lineedit_codeformat_other_control->setText(code_format.value("other_control").toString());
    ui->textedit_codeformat_summary->setPlainText(code_format.value("summary").toString());

    QJsonObject intelligence = parent.value("intelligence").toObject();
    ui->spinbox_tip_delay->setValue(intelligence.value("delay").toInt());

    QJsonObject toolbar = parent.value("toolbar").toObject();
    ui->checkbox_build->setChecked(toolbar.value("checkbox_build") == "true");
    ui->checkbox_debug->setChecked(toolbar.value("checkbox_debug") == "true");
    ui->checkbox_std->setChecked(toolbar.value("checkbox_std") == "true");
    ui->checkbox_textedit->setChecked(toolbar.value("checkbox_textedit") == "true");


    // 读取快捷键
    QJsonArray array = parent.value("快捷键").toArray();
    foreach(QJsonValue value, array)
    {
        QJsonObject object = value.toObject();
        QString name = object.value("类别").toString();
        auto item = new QTreeWidgetItem(ui->shortcut_treewidget);
        item->setExpanded(true);
        item->setText(0, name);

//        QFont font = item->font(0);
//        font.setBold(true);
//        item->setFont(0, font);

        QJsonArray item_array = object.value("项目").toArray();
        foreach(QJsonValue value, item_array)
        {
            QJsonObject item_obj = value.toObject();
            auto child = new QTreeWidgetItem(item);
            QString name = item_obj.value("name").toString();
            QString short_cut = item_obj.value("short").toString();
            child->setText(0, name);
            child->setText(1, short_cut);
        }
    }
}

void VSettingDialog::load_color_setting(QString path)
{
    // 读取颜色配置
    ui->color_listwidget->clear();
    QJsonArray array1 = VFunctions::get_file_jsonDocument(path)
            .object().value("color").toArray();
    foreach(QJsonValue value, array1)
    {
        QJsonObject object = value.toObject();
        QString name = object.value("name").toString();
        QString fore = object.value("fore").toString();
        QString back = object.value("back").toString();
        bool bold = object.value("bold").toString() == "true";
        bool italics = object.value("italic").toString() == "true";
        QString mark = object.value("mark").toString();
        auto item = new QListWidgetItem();
        item->setText(name);
        item->setForeground(QBrush(QColor(fore.toInt(nullptr, 16))));
        item->setBackground(QBrush(QColor(back.toInt(nullptr, 16))));

        QFont font = item->font();
        font.setBold(bold);
        font.setItalic(italics);

        item->setFont(font);
        item->setData(Qt::UserRole, QVariant::fromValue(mark));
        ui->color_listwidget->addItem(item);
    }

    if(ui->color_listwidget->count()>0)
        ui->color_listwidget->setCurrentRow(0);

}


void VSettingDialog::on_pushButton_3_clicked()
{
    this->reject();
}
